<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 函数嵌套调用
    // debugger;

    // 函数func fn执行完毕 对应的AO对象都被释放  => 下次调用重新创建新的AO对象
    /* function fn() {
        var a = 10;  // 局部变量 AO(fn) {a:10 => 11}
        function func() {
            // AO(func) {}
            a++;
            console.log(a);
            return a;  // 11
        }
        return func();
    }

    var result = fn();
    console.log(result);

    var result = fn();
    console.log(result);

    var result = fn();
    console.log(result); */



    // 闭包:
    // 闭包是指    有权访问另一个函数作用域中的变量    的函数。
    // 简单的来说  就是 一个函数在执行过程中 返回另一个函数/对象 (引用类型   一般都是函数)

    // 如何形成闭包?
    // 1. 在函数内容中, 返回一个引用类型(数组, 对象, 函数, 以函数为主)
    // 2. 返回的引用类型(数组, 对象, 函数, 以函数为主), 使用父函数中的局部作用域变量
    // 3. 在函数的外部, 有变量来引用 引用类型

    // 函数在执行过程中返回了另一个函数, 该函数使用父函数中的变量或方法, 导致返回的函数通过作用域链一直引用父作用域的AO对象导致父作用域的AO对象一直得不到释放

    // 优点:
    //  1. 闭包中的数据只要不释放,可以一直存储(长时间存储数据)
    //  2. 可以在函数外访问函数内的数据
    //  3. 减少全局变量的使用 (模块化) 

    // 缺点:
    // 1. 父作用域的AO对象一直得不到释放,占内存; 如果闭包使用频率过高会导致内存泄漏
    // 2. 函数外可以访问函数内的数据,不安全


    /* function fn() {
        var a = 10;  // 局部变量 AO(fn) {a:10 => 11,12,13 }

        function func() {
            // AO(func) {}
            a++;
            console.log(a);
            return a;  // 11 
        }
        return func; // fn的返回值是一个函数(特殊的对象=>引用类型)
    }

    var result = fn();  // result 和 func引用同一片内存地址 ,调用result等价调用func
    console.log(result);


    result();
    result();
    result();
    result();
    result();
 */

    debugger;
    function fn() {
        var a = 10;  // 11
        return function () {
            a++;
            console.log(a);
            return a;
        }
    }

    var newFn = fn();
    console.log(newFn);
    newFn();
    newFn();
    newFn();
    newFn();
    newFn();


    /*  var newFn = fn();
     console.log(newFn);
     newFn();
     newFn();
     newFn();
     newFn();
     newFn();
  */





</script>

</html>